#pragma once

#include <string>
#include <vector>
#include <glad/glad.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

namespace mygl {

class Shader {
 public:
  Shader(std::string vertex_path, std::string fragment_path,
         std::string glsl_impl = std::string());

  ~Shader();
  unsigned int program_id() const { return program_id_; }

  int Init();
  void UseProgram() const;
  void DeleteProgram() const;

  void SetUniformInt(const std::string &name, int value, bool use = false);
  void SetUniformFloat(const std::string &name, float value, bool use = false);
  void SetUniformVecnFloat(const std::string &name, int n,
                           const std::vector<float> &values);
  void SetUniformVec2Float(const std::string &name, glm::vec2 trans, bool use = false);
  void SetUniformVec3Float(const std::string &name, glm::vec3 trans, bool use = false);
  void SetUniformVec4Float(const std::string &name, glm::vec4 trans, bool use = false);
  void SetUniformMat4Float(const std::string &name, const float *value, bool use = false);
  void SetUniformMat4Float(const std::string &name, glm::mat4 trans, bool use = false);
  void SetUniformMat3Float(const std::string &name, glm::mat3 trans, bool use = false);

 private:
  int compile(const char *vertex_source, const char *fragment_source);
  static int checkCompileErrors(GLuint shader, const char *prefix);
  static int checkLinkErrors(GLuint program, const char *prefix);

 private:
  std::string vertex_path_;
  std::string fragment_path_;
  std::string glsl_impl_;  // transition glsl implement
  GLuint program_id_;
};

}  // namespace mygl